package com.woniu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.dto.AddGoodsTypeDto;

import com.woniu.dto.GoodsTypeDto;
import com.woniu.exception.RebornException;
import com.woniu.execption.goodstype.GoodsTypeException;
import com.woniu.execption.goodstype.GoodsTypeExceptionCode;
import com.woniu.mapper.GoodsMapper;
import com.woniu.mapper.GoodsTypeMapper;
import com.woniu.model.Goods;
import com.woniu.model.GoodsType;
import com.woniu.params.*;
import com.woniu.service.GoodsTypeService;
import com.woniu.utils.StateData;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年05月25日
 */
@Service
@Transactional
public class GoodsTypeServiceImpl extends ServiceImpl<GoodsTypeMapper, GoodsType> implements GoodsTypeService {
    @Autowired
    private GoodsTypeMapper goodsTypeMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public GoodsType addGoodsType(AddGoodsTypeParam param) {
        //商品类型名是否重复
        GoodsType goodsType = this.getOne(new QueryWrapper<GoodsType>().eq("type_name", param.getTypeName()));
        if (goodsType!=null) {
            throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_NOT_EXITS);
        }
        GoodsType type = BeanUtil.toBean(param, GoodsType.class);
        type.setTypeSelf(StateData.GOODS_TYPE_NOT_SELF);
        type.setTypeName(param.getTypeName());
        //没有父节点的情况
        if (param.getParentId()==0){
            //判断类型名称是否相同
            type.setParentId(StateData.GOODS_DEFAULT_PARENT);
            type.setState(StateData.GOODS_STATE_NORMAL);
            save(type);
            return  type;
        }
        //有父节点的情况
        //1.判断父节点是否存在
        GoodsType parentGoodsType = this.getOne(new QueryWrapper<GoodsType>().eq("id", param.getParentId()));
        if (parentGoodsType==null) throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_PARENTID_NOT_EXITS);
        if (parentGoodsType.getTypeSelf().longValue()==StateData.GOODS_TYPE_NOT_SELF){
            parentGoodsType.setTypeSelf(StateData.GOODS_TYPE_IS_SELF);
        }
        type.setState(parentGoodsType.getState());
        type.setParentId(parentGoodsType.getId());
        save(type);
        updateById(parentGoodsType);
        return  type;
    }

    @Override
    public List<GoodsType> disable(Integer typeId) {
        GoodsType goodsType = getById(typeId);
        if (goodsType==null) {
            throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_NOT_EXITS);
        }
        if (goodsType.getState().longValue()!=StateData.GOODS_TYPE_STATE_NORMAL){
            throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_STATE_ERROR);
        }

        ArrayList<Integer> list = new ArrayList<>();
        list.add(typeId);
        findChildId(typeId,list);

        UpdateWrapper<GoodsType> wrapper = new UpdateWrapper<>();
        wrapper.set("state",StateData.GOODS_TYPE_STATE_DISABLE);
        wrapper.in("id",list);
        goodsTypeMapper.update(null,wrapper);

        UpdateWrapper<Goods> bookInfoWrapper = new UpdateWrapper<>();
        bookInfoWrapper.set("state",2);
        bookInfoWrapper.in("type_id",list);
        goodsMapper.update(null,bookInfoWrapper);
        return null;
    }

    @Override
    public void enable(Integer typeId) {
        //解禁
        //通过递归找到当前类别的所有父类别
        ArrayList<Integer> list = new ArrayList<>();
        list.add(typeId);
        findParentId(typeId, list);
        //执行更新
        UpdateWrapper<GoodsType> wrapper = new UpdateWrapper<>();
        wrapper.set("state", StateData.GOODS_STATE_NORMAL);
        wrapper.in("id", list);
        goodsTypeMapper.update(null, wrapper);

        UpdateWrapper<Goods> bookInfoWrapper = new UpdateWrapper<>();
        bookInfoWrapper.set("state",0);
        bookInfoWrapper.in("type_id",list);
        goodsMapper.update(null,bookInfoWrapper);
    }

    @Override
    public void modify(Integer parentId, Integer typeId) {
        //找到新父级图书类别 的数据
        GoodsType newParentType = goodsTypeMapper.selectById(parentId);
        if (newParentType==null) {
            throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_NOT_EXITS);
        }
        if (newParentType.getState().intValue()!=StateData.GOODS_TYPE_STATE_NORMAL) throw new GoodsTypeException(GoodsTypeExceptionCode.GOODSTYPE_STATE_ERROR);
        //找到被修改的类别 的原本 父亲类别(老父级节点)
        // 判断老父级节点 子节点数量是否大于1 大于1就不用修改 其叶子节点状态
        GoodsType GoodsType = goodsTypeMapper.selectById(typeId);
        GoodsType oldParentType = goodsTypeMapper.selectById(GoodsType.getParentId());
        QueryWrapper<GoodsType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",oldParentType.getId());
        //老父级节点的所有 子节点的数据
        List<GoodsType> oldParentTypes = goodsTypeMapper.selectList(wrapper);
        //等于1 说明没有除被修改的子节点 以外的节点 要修改其叶子节点的状态
        if (oldParentTypes.size()==1){
            oldParentType.setTypeSelf(StateData.GOODS_TYPE_NOT_SELF);
            goodsTypeMapper.updateById(oldParentType);
        }
        //判断新类别的叶子节点状态
        if (newParentType.getTypeSelf().intValue()!=StateData.GOODS_TYPE_IS_SELF){
            newParentType.setTypeSelf(StateData.GOODS_TYPE_IS_SELF);
            goodsTypeMapper.updateById(newParentType);
        }
        //最后更新被修改的图书类别
        GoodsType.setParentId(newParentType.getId());
        GoodsType.setTypeSelf(newParentType.getState());
        goodsTypeMapper.updateById(GoodsType);
    }

    /**
     * 查询所有商品类别Page
     * @param param page分页param
     * @return page
     */
    @Override
    public Page<GoodsType> getAll(pageParam param) {
        int pageNum =param.getPageNum() == 0 ? 1 : param.getPageNum();
        int pageSize =param.getPageSize() == 0 ? 3 : param.getPageSize();
        Page<GoodsType> page = new Page<>(pageNum, pageSize);
        return goodsTypeMapper.selectPage(page, new QueryWrapper<>());
    }

    /**
     * 查询所有商品类别list
     * @return list
     */
    @Override
    public List<GoodsType> getAllList() {
        return goodsTypeMapper.selectList(new QueryWrapper<>());
    }

    /**
     * 禁用某个商品类别
     * @param param 改变状态param
     * @return null
     */
    @Override
    public void changeStatus(ChangeStatusParam param) {
        if (Objects.equals(param.getState(), StateData.GOODS_TYPE_STATE_NORMAL)){
            enable(param.getTypeId());
        }else{
            disable(param.getTypeId());
        }
    }

    @Override
    public List<GoodsType> findUseFulType(FindUseFulTypeParam param) {

        //根据当前节点的typeId进行筛选 1.筛除掉自己的子类 因为父类不能改成自己儿子 2.不能是当前的父类
        //1.找到自己当前所有的子类id
        List<GoodsType> sons1 = new ArrayList<>();
        List<GoodsType> sons =  findSonType(param.getTypeId(),sons1);
        //遍历添加筛选条件
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        for (GoodsType son : sons) {
            queryWrapper.ne("id",son.getId());
        }

        //2.排除当前自己的父亲
        if (param.getParentId()!=0){
            queryWrapper.ne("id",param.getParentId());
        }
        //3.排除自己
        queryWrapper.ne("id",param.getTypeId());


        List<GoodsType> useFulTypes = goodsTypeMapper.selectList(queryWrapper);
        System.out.println("返回到前端的usefulTypes: "+useFulTypes.toString());
        return useFulTypes;
    }

    /**
     * 更改商品父类
     * @param param 更改父类param
     * @return null
     */
    @Override
    public void changeFatherNow(ChangeFatherNowParam param) {
        if (param.getNewParentId()!=0){
            //有新爹的情况下 看看新爹是不是叶子结点
            GoodsType newFather = goodsTypeMapper.selectById(param.getNewParentId());
            if (Objects.equals(newFather.getTypeSelf(), StateData.TYPE_IS_SELF)){
                newFather.setTypeSelf(StateData.TYPE_NOT_SELF);
                goodsTypeMapper.updateById(newFather);
            }
        }
        UpdateWrapper<GoodsType> updateWrapper = new UpdateWrapper<>();
        GoodsType newGoodsType = new GoodsType();
        newGoodsType.setId(param.getTypeId());
        newGoodsType.setParentId(param.getNewParentId());
        GoodsType father = null;
        if (param.getOldParentId()!=0){
            father = goodsTypeMapper.selectById(param.getOldParentId());
            //有爹的情况下 先把爹查出来 查看状态
            if (Objects.equals(father.getState(), StateData.GOODS_TYPE_STATE_DELETE)){
                throw new RebornException("商品状态异常",90001);
            }
            //初始状态为爹的状态
            newGoodsType.setState(father.getState());
            //查询当前爹所有的儿子 如果只有当前类一个儿子 则把当前爹改为叶子结点
            UpdateWrapper<GoodsType> fatherWrapper = new UpdateWrapper<>();
            fatherWrapper.eq("parent_id",father.getId());
            List<GoodsType> fatherTypes = goodsTypeMapper.selectList(fatherWrapper);
            if (fatherTypes.size()>=1){
                father.setTypeSelf(StateData.TYPE_NOT_SELF);
                goodsTypeMapper.updateById(father);
            }else{
                father.setTypeSelf(StateData.TYPE_IS_SELF);
                goodsTypeMapper.updateById(father);
            }
        }
        if (param.getNewParentId()==0){
            newGoodsType.setTypeSelf(StateData.TYPE_IS_SELF);
        }else{
            newGoodsType.setTypeSelf(StateData.GOODS_TYPE_NOT_SELF);
        }
        newGoodsType.setParentId(param.getNewParentId());
        //思考 不用移动儿子 因为儿子跟着自己
        goodsTypeMapper.updateById(newGoodsType);

    }

    /**
     * 删除商品类型
     * @param typeId 类别id
     */
    @Override
    public void delType(Integer typeId) {
        GoodsType goodsType = goodsTypeMapper.selectById(typeId);
        if (goodsType == null) {
            throw new RebornException("不存在的商品类型",50001);
        }
        if (Objects.equals(goodsType.getState(),StateData.GOODS_TYPE_STATE_DELETE)) {
            throw new RebornException("该商品类型已是删除状态",50002);
        }
        //通过递归找到当前类别的所有子类别
        ArrayList<Integer> list = new ArrayList<>();
        list.add(typeId);
        findChildren(typeId, list);
        //执行删除
        UpdateWrapper<GoodsType> wrapper = new UpdateWrapper<>();
        wrapper.set("state", StateData.GOODS_TYPE_STATE_DELETE);
        wrapper.in("id", list);
        goodsTypeMapper.update(null, wrapper);
        //将商品也变成删除状态
        for (Integer id : list) {
            QueryWrapper<Goods> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("type_id",id);
            List<Goods> goodsTypes = goodsMapper.selectList(wrapper1);
            for (Goods goods : goodsTypes) {
                goods.setState(StateData.GOODS_TYPE_STATE_DELETE);
                goodsMapper.updateById(goods);
            }
        }
        //找到改商品的父节点 如果父节点只有该节点 修改父节点的 叶子节点状态(非叶子节点)
        if (goodsType.getParentId()!=0){
            GoodsType parentType = getById(goodsType.getParentId());

            List<GoodsType> sonTypeList = list(new QueryWrapper<GoodsType>().eq("parent_id", parentType.getId()).eq("state",0));
            if (sonTypeList==null||sonTypeList.size()==0) {
                parentType.setTypeSelf(0);
                updateById(parentType);
            }
        }


    }


    /**
    递归查找儿子
     */
    private void findChildren(Integer typeId, ArrayList<Integer> list) {
        QueryWrapper<GoodsType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", typeId);
        wrapper.ne("state",StateData.GOODS_TYPE_STATE_DELETE);
        //通过typeId查询该类别下的所有子类别
        List<GoodsType> children = goodsTypeMapper.selectList(wrapper);
        //归条件 当前已没有儿子
        if (children == null || children.size() == 0) {
            return;
        }
        for (GoodsType childrenType : children) {
            list.add(childrenType.getId());
            //递归查询
            findChildren(childrenType.getId(), list);
        }
    }

    private List<GoodsType> findSonType(Integer typeId, List<GoodsType> sons ) {
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("parent_id",typeId);
        //找到自己的一级儿子
        List<GoodsType> GoodsTypes = goodsTypeMapper.selectList(queryWrapper);
        //遍历一级儿子 找到其所有子类 加入集合
        if (GoodsTypes!=null && !GoodsTypes.isEmpty()){//如果当前已是叶子结点 则终止递归
            for (GoodsType GoodsType : GoodsTypes) {
                sons.add(GoodsType);
                findSonType(GoodsType.getId(),sons);
            }
        }

        return sons;
    }

    public void findChildId(Integer typeId,List<Integer> list){
        QueryWrapper<GoodsType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",typeId);
        wrapper.ne("state",StateData.GOODS_TYPE_STATE_DELETE);
        List<GoodsType> GoodsTypes = goodsTypeMapper.selectList(wrapper);
        if (GoodsTypes==null||GoodsTypes.size()==0){
            return;
        }
        for (GoodsType GoodsType : GoodsTypes) {
            list.add(GoodsType.getId());
            findChildId(GoodsType.getId(),list);
        }
    }

    public void findParentId(Integer parentId,List<Integer> list){
        QueryWrapper<GoodsType> wrapper = new QueryWrapper<>();
        wrapper.eq("id",parentId);

        GoodsType parentType = goodsTypeMapper.selectOne(wrapper);

        if (parentType!=null){
            list.add(parentType.getId());
            findParentId(parentType.getParentId(),list);
        }

    }

    public void findChildType(GoodsTypeDto dto){
        QueryWrapper<GoodsType> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",dto.getId());
        wrapper.eq("state",StateData.GOODS_TYPE_STATE_NORMAL);
        List<GoodsType> list = goodsTypeMapper.selectList(wrapper);

        if (list!=null&&list.size()>0){
            for (GoodsType GoodsType : list) {
                GoodsTypeDto childDto = BeanUtil.toBean(GoodsType, GoodsTypeDto.class);
                dto.getBookTypeDtos().add(childDto);
                findChildType(childDto);
            }
        }

    }
//    @Override
//    public List<AddGoodsTypeDto> addGoodsType(List<AddGoodsTypeParam> params) {
//        //首先判断集合的父节点 是否存在
//        //判断类型名是否相同
//        //新增为父节点 直接新增
//        return null;
//    }
}
